package com.example.starter.verticle;

import com.example.starter.conf.Constants;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.StaticHandler;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.LockSupport;

/**
 * @author yangkui
 */
public class WebVerticle extends AbstractVerticle {
	private int counter;

	@Override
	public void start() {
		var httpConf = config().getJsonObject(Constants.HTTP);
		var port = httpConf.getInteger(Constants.PORT);

		vertx.createHttpServer().requestHandler(router()).listen(port)
				.onSuccess(v -> System.out.println("HTTP server started on port " + port))
				.onFailure(e -> System.out.println("Failed to start HTTP server: " + e.getMessage()));
	}

	private Router router() {
		var router = Router.router(vertx);

		// 解析POST请求体
		router.post().handler(BodyHandler.create());

		// 静态网页解析
		router.route("/static/*").handler(StaticHandler.create("static"));

		// hello world
		router.get("/").handler(ctx -> ctx.end("Hello World!"));

		// 类成员变量自增(线程安全)
		router.get("/incr").handler(ctx -> {
			counter = counter + 1;
			ctx.response().end(String.valueOf(counter));
		});

		// 使用Promise封装异步任务结果并提交到EventLoop
		var context = vertx.getOrCreateContext();
		router.get("/mock").handler(ctx -> {
			var future = mock();
			var now = System.currentTimeMillis();
			future.onComplete(ar -> {
				var callbackThread = Thread.currentThread().getName();
				context.runOnContext(v -> {
					if (ar.succeeded()) {
						var json = new JsonObject();
						json.put("requestTime", now);
						json.put("responseTime", ar.result());
						json.put("callbackThread", callbackThread);
						json.put("processThread", Thread.currentThread().getName());
						ctx.json(json);
					} else {
						ctx.fail(ar.cause());
					}
				});
			});
		});


		// 获取当前在线客户端数量
		router.get("/online").handler(ctx -> {
			var json = new JsonObject().put(Constants.TYPE, Constants.ONLINE);
			var future = vertx.eventBus().request(TCPVerticle.TCP_EVENT_BUS_ADDRESS, json);
			future.onSuccess(message -> ctx.json(message.body())).onFailure(ctx::fail);
		});

		// 查询数据库表列
		router.get("/queryColumns/:" + Constants.SCHEMA + "/:" + Constants.TABLE).handler(ctx -> {
			var schema = ctx.pathParam(Constants.SCHEMA);
			var table = ctx.pathParam(Constants.TABLE);
			var json = new JsonObject();
			json.put(Constants.SCHEMA, schema);
			json.put(Constants.TABLE, table);

			vertx.eventBus().request(RepositoryVerticle.REPOSITORY_EVENT_BUS_ADDRESS, json, ar -> {
				if (ar.succeeded()) {
					ctx.json(ar.result().body());
				} else {
					ctx.fail(ar.cause());
				}
			});
		});
		return router;
	}

	private Future<Long> mock() {
		var promise = Promise.<Long>promise();
		CompletableFuture.runAsync(() -> {
			LockSupport.parkUntil(System.currentTimeMillis() + 10000);
			promise.complete(System.currentTimeMillis());
		});
		return promise.future();
	}
}
